package edu.uclmgmu.bacteriosec.aspects.common;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Vector;

import edu.uclmgmu.bacteriosec.domain.FiltroGenerico;

public class FilesStore {
	/***
	 * Executed by *_CountCalls
	 * @param signature
	 */
	public static void updateNumberOfCalls(String catchedMethod, String testCaseName) {
		String folder=System.getProperty("java.io.tmpdir") + catchedMethod + ".counter"; 
		(new java.io.File(folder)).mkdir();
		try {
			createCallCounter(folder);
		}
		catch (FileNotFoundException e) {
			System.out.println("FileNotFoundException inesperada en createCallCounter");
		}
		catch (Exception e) {
			System.out.println("Error creando callCounter.txt en " + folder);
		}
		try {
			createStartFile(folder, testCaseName);
		}
		catch (Exception e) {
			System.out.println("Error creando startFile para " + folder + " y " + testCaseName);
		}
		try {
			createEndFile(folder, testCaseName);
		}
		catch (Exception e) {
			System.out.println("Error creando endFile para " + folder + " y " + testCaseName);
		}
		try {
			updateCallCounter(folder);
		} catch (FileNotFoundException e1) {
			System.out.println("FileNotFoundException inesperada actualizando " + folder + "/callCounter.txt");
		} catch (IOException e) {
			System.out.println("Error actualizando " + folder + "/callCounter.txt: " + e.toString());
		}
		int numberOfCalls=1;
		String fileName=folder + "/" + testCaseName  + ".numberOfCalls";
		try {
			DataInputStream dis=new DataInputStream(new FileInputStream(fileName));
			numberOfCalls=dis.readInt();
			dis.close();
			numberOfCalls+=1;
		}
		catch (FileNotFoundException e) {
		}
		catch(Exception e) {
			System.out.println(e.toString());
		}	
		try {
			DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName));
			dos.writeInt(numberOfCalls);
			dos.close();
			// TODO : borrar
			FileOutputStream fos=new FileOutputStream(fileName + ".txt");
			fos.write((""+numberOfCalls).getBytes());
			fos.close();
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	}
	
	public static void createCallCounter(String folder) throws IOException {
		String fileName=folder + "/callCounter";
		try {
			FileInputStream fi=new FileInputStream(fileName);
			fi.close();
			return;
		}
		catch (FileNotFoundException e) {}
		FileOutputStream fos=new FileOutputStream(fileName + ".txt");
		fos.write(("1").getBytes());
		fos.close();
		
		DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName));
		dos.writeInt(1);
		dos.close();
	}
	
	private static void updateCallCounter(String folder) throws FileNotFoundException, IOException {
		String fileName=folder + "/callCounter";
		FileInputStream fi=new FileInputStream(fileName + ".txt");
		byte[] b=new byte[fi.available()];
		fi.read(b);
		fi.close();
		String sn=new String(b);
		int n=Integer.parseInt(sn);
		n=n+1;
		sn=""+n;
		FileOutputStream fos=new FileOutputStream(fileName + ".txt");
		fos.write(sn.getBytes());
		fos.close();
		
		DataInputStream di=new DataInputStream(new FileInputStream(fileName));
		n=di.readInt();
		n=n+1;
		di.close();
		DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName));
		dos.writeInt(n);
		dos.close();
	}
	
	private static int readCallCounter(String folder) throws FileNotFoundException, IOException {
		String fileName=folder + "/callCounter";
		DataInputStream di=new DataInputStream(new FileInputStream(fileName));
		int n=di.readInt();
		di.close();
		return n;
/*		String fileName=folder + "/callCounter.txt";
		FileInputStream fi=new FileInputStream(fileName);
		byte[] b=new byte[fi.available()];
		fi.read(b);
		fi.close();
		String sn=new String(b);
		int n=Integer.parseInt(sn);
		return n;*/
	}
	
	private static void createEndFile(String path, String testCaseName) throws FileNotFoundException, IOException {
		String endFileName=path + "/" + testCaseName + ".end";
		int n=readCallCounter(path);
		DataOutputStream dos=new DataOutputStream(new FileOutputStream(endFileName));
		dos.writeInt(n);
		dos.close();
		
		String sn=""+n;
		FileOutputStream fos=new FileOutputStream(endFileName + ".txt");
		fos.write(sn.getBytes());
		fos.close();
	}

	private static void createStartFile(String folder, String testCaseName) throws FileNotFoundException, IOException {
		String startFileName=folder + "/" + testCaseName + ".start";
		try {
			FileInputStream fi=new FileInputStream(startFileName);
			fi.close();
			return;
		}
		catch (FileNotFoundException e) {}		
		int n=1;
		try {
			n=readCallCounter(folder);
		}
		catch (FileNotFoundException e) {			
		}
		DataOutputStream dos=new DataOutputStream(new FileOutputStream(startFileName));
		dos.writeInt(n);
		dos.close();
		
		String sn="" + n;
		FileOutputStream fos=new FileOutputStream(startFileName + ".txt");
		fos.write(sn.getBytes());
		fos.close();
	}

	public static int getNumberOfCallInTurn(String joinPointName) {
		String fileName=System.getProperty("java.io.tmpdir") + joinPointName + ".numberOfCallInTurn";
		int result=-1;
		try {
			DataInputStream dis=new DataInputStream(new FileInputStream(fileName));
			result=dis.readInt();
			dis.close();

		}
		catch(Exception e) {
			System.out.println(e.toString());
		}
		return result;
	}

	public static int getNumberOfCurrentCall(String joinPointName) {
		String fileName=System.getProperty("java.io.tmpdir") + joinPointName + ".numberOfCurrentCall";
		int result=-1;
		FileNotFoundException fnfe=null;
		try {
			DataInputStream dis=new DataInputStream(new FileInputStream(fileName));
			result=dis.readInt();
			dis.close();
		}
		catch(FileNotFoundException e){
			fnfe = e;
		}
		catch(IOException e) {
			System.out.println("Error en getNumberOfCurrentCall " + e.toString());
		}
		if (fnfe!=null) {
			try {
				DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName));
				dos.writeInt(1);
				dos.close();
				result=1;
				// TODO: borrar
				
			} catch (Exception e) {
				System.out.println(e.toString());
			}
		}
		return result;
	}

	public static void updateNumberOfCurrentCall(String joinPointName) {
		String fileName=System.getProperty("java.io.tmpdir") + joinPointName + ".numberOfCurrentCall";
		try {
			DataInputStream dis=new DataInputStream(new FileInputStream(fileName));
			int currentCall=dis.readInt();
			dis.close();
			currentCall++;
			
			DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName));
			dos.writeInt(currentCall);
			dos.close();
			// TODO: borrar
			FileOutputStream auxi=new FileOutputStream(fileName+".txt");
			auxi.write((""+currentCall).getBytes());
			auxi.close();
		}
		catch(Exception e) {
			//System.out.println("ERRORZACO: " + e.toString());
		}	
	}

	public static void log(String canonicalName, int numberOfCurrentCall, String signature) {
//		String text="Operator: " + canonicalName + "\nCurrent call: " + numberOfCurrentCall + "\nJoin point:" + signature + "\n\n";
//		System.out.println(text);
	}

	public static String getCurrentjoinPoint() {
		String fileName=System.getProperty("java.io.tmpdir") + "currentJoinPoint.txt";
		String result=null;
		try {
			FileInputStream dis=new FileInputStream(fileName);
			byte[] b=new byte[dis.available()];
			dis.read(b);
			dis.close();
			result=new String(b);
		}
		catch(Exception e) {
			System.out.println("Error leyendo currentJoinPoint.txt-> " + e.toString());
		}
		return result;
	}

	public static int getNumberOfCallsToJP(String jpFile) {
		try {
			DataInputStream dis=new DataInputStream(new FileInputStream(jpFile + ".numberOfCalls"));
			int numberOfCallsToJP=dis.readInt();
			dis.close();
			return numberOfCallsToJP;
		} catch (Exception e) {
			return -1;
		}
	}

	public static void saveCurrentJoinPoint(String jpName) {
		String tempPath=System.getProperty("java.io.tmpdir");
		try {
			FileOutputStream fos=new FileOutputStream(tempPath + "currentJoinPoint.txt");
			fos.write(jpName.getBytes());
			fos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void createFileForCallInTurn(String joinPointName, int callInTurn) {
		try {
			String fileName=joinPointName + ".numberOfCallInTurn";
			DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName));
			dos.writeInt(callInTurn);
			dos.close();
			// TODO: borrar
			FileOutputStream auxi=new FileOutputStream(fileName+".txt");
			auxi.write((""+callInTurn).getBytes());
			auxi.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void createFileForCurrentCall(String methodCatchedName, String testCaseName, int callInTurn) {
		try {
			String fileName=System.getProperty("java.io.tmpdir") + "currentCall.txt";
			FileOutputStream auxi=new FileOutputStream(fileName);
			auxi.write((methodCatchedName+"\n").getBytes());
			auxi.write((testCaseName+"\n").getBytes());
			auxi.write((""+callInTurn).getBytes());
			auxi.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
	
	public static void createFileForCallInTurn(String methodCatchedName, String testCaseName, int callInTurn) {
		try {
			String fileName=System.getProperty("java.io.tmpdir") + "callInTurn.txt";
			FileOutputStream auxi=new FileOutputStream(fileName);
			auxi.write((methodCatchedName+"\n").getBytes());
			auxi.write((testCaseName+"\n").getBytes());
			auxi.write((""+callInTurn).getBytes());
			auxi.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
	
	public static String loadCurrentMethod() {
		String result=null;
		try {
			String fileName=System.getProperty("java.io.tmpdir") + "currentCall.txt";
			FileInputStream fi=new FileInputStream(fileName);
			BufferedReader br = new BufferedReader(new InputStreamReader(fi));
			result=br.readLine();
			fi.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	public static String loadCurrentTestCase() {
		String result=null;
		try {
			String fileName=System.getProperty("java.io.tmpdir") + "currentCall.txt";
			FileInputStream fi=new FileInputStream(fileName);
			BufferedReader br = new BufferedReader(new InputStreamReader(fi));
			result=br.readLine();
			result=br.readLine();
			fi.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	public static int loadCurrentCall() {
		int result=0;
		try {
			String fileName=System.getProperty("java.io.tmpdir") + "currentCall.txt";
			FileInputStream fi=new FileInputStream(fileName);
			BufferedReader br = new BufferedReader(new InputStreamReader(fi));
			String linea=br.readLine();
			linea=br.readLine();
			linea=br.readLine();
			fi.close();
			result=Integer.parseInt(linea);
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	public static String loadMethodInTurn() {
		String result=null;
		try {
			String fileName=System.getProperty("java.io.tmpdir") + "callInTurn.txt";
			FileInputStream fi=new FileInputStream(fileName);
			BufferedReader br = new BufferedReader(new InputStreamReader(fi));
			result=br.readLine();
			fi.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	public static String loadTestCaseInTurn() {
		String result=null;
		try {
			String fileName=System.getProperty("java.io.tmpdir") + "callInTurn.txt";
			FileInputStream fi=new FileInputStream(fileName);
			BufferedReader br = new BufferedReader(new InputStreamReader(fi));
			result=br.readLine();
			result=br.readLine();
			fi.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	public static int loadCallInTurn() {
		int result=0;
		try {
			String fileName=System.getProperty("java.io.tmpdir") + "callInTurn.txt";
			FileInputStream fi=new FileInputStream(fileName);
			BufferedReader br = new BufferedReader(new InputStreamReader(fi));
			String linea=br.readLine();
			linea=br.readLine();
			linea=br.readLine();
			fi.close();
			result=Integer.parseInt(linea);
			return result;
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	public static void saveAOP_AJC_XML(String aopXMLPath, String text) throws IOException {
		FileOutputStream fos=new FileOutputStream(aopXMLPath);
		fos.write(text.getBytes());
		fos.close();
	}
	
	public static int readNumberOfCalls(String catchedMethod, String testCaseName) throws IOException {
		String tempPath=System.getProperty("java.io.tmpdir");
		String fileName=tempPath + catchedMethod + ".counter/" + testCaseName + ".numberOfCalls";
		int n=0;
		DataInputStream dis=new DataInputStream(new FileInputStream(fileName));
		n+=dis.readInt();
		dis.close();
		return n;
	}
	
	public static int readStartingCall(String catchedMethod, String testCaseName) throws IOException {
		String tempPath=System.getProperty("java.io.tmpdir");
		String fileName=tempPath + catchedMethod + ".counter/" + testCaseName + ".start";
		int n=0;
		DataInputStream dis=new DataInputStream(new FileInputStream(fileName));
		n+=dis.readInt();
		dis.close();
		return n;
	}
	
	public static int readEndCall(String catchedMethod, String testCaseName) throws IOException {
		String tempPath=System.getProperty("java.io.tmpdir");
		String fileName=tempPath + catchedMethod + ".counter/" + testCaseName + ".end";
		int n=0;
		DataInputStream dis=new DataInputStream(new FileInputStream(fileName));
		n+=dis.readInt();
		dis.close();
		return n;
	}

	public static int readNumberOfCalls(String catchedMethod) throws IOException {
		String tempPath=System.getProperty("java.io.tmpdir");
		String directorio=tempPath + catchedMethod + ".counter";
		FiltroGenerico fg=new FiltroGenerico();
		Vector<String> testFiles = fg.loadFiles(directorio, ".numberOfCalls");
		int n=0;
		for (String testFile : testFiles) {
			DataInputStream dis=new DataInputStream(new FileInputStream(testFile + ".numberOfCalls"));
			n+=dis.readInt();
			dis.close();
		}
		return n;
	}
	
	public static void createFileForCurrentCall(String joinPointName, int currentCall) throws IOException {
		String fileName=joinPointName + ".numberOfCurrentCall";
		DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName));
		dos.writeInt(currentCall);
		dos.close();
		// TODO: borrar
		FileOutputStream auxi=new FileOutputStream(fileName+".txt");
		auxi.write((""+currentCall).getBytes());
		auxi.close();
	}
	
/*	public static void createFileForCurrentCall(String catchedMethod, String testCaseName, int currentCall) throws IOException {
		String fileName=System.getProperty("java.io.tmpdir") + catchedMethod + ".counter/" + testCaseName + ".numberOfCurrentCall";
		DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName));
		dos.writeInt(currentCall);
		dos.close();
		// TODO: borrar
		FileOutputStream auxi=new FileOutputStream(fileName+".txt");
		auxi.write((""+currentCall).getBytes());
		auxi.close();
	}*/

	public static Vector<String> loadFilesNumberOfCalls() {
		String tempPath=System.getProperty("java.io.tmpdir");
		FiltroGenerico fg=new FiltroGenerico();
		Vector<String> directoriosCounter=fg.loadFiles(tempPath, ".counter");
		Vector<String> result=new Vector<String>();
		for (String directorio :directoriosCounter) {
			Vector<String> jpFiles=fg.loadFiles(directorio, ".numberOfCalls");
			for (String jpFileName : jpFiles) {
				jpFileName=jpFileName.substring(0, jpFileName.length()-".numberOfCalls".length());
				result.add(jpFileName);
			}
		}
		return result;
	}
	
	public static void main(String[] args) throws IOException {
		System.out.println(FilesStore.loadCurrentMethod());
		System.out.println(FilesStore.loadCurrentTestCase());
		System.out.println(FilesStore.loadCurrentCall());
	}

	public static void cleanTempPath(String methodCatched) {
		String directory=System.getProperty("java.io.tmpdir") + methodCatched + ".counter";
		FiltroGenerico fg=new FiltroGenerico();
		Vector<String> files = fg.loadFiles(directory, null);
		for (String file : files) {
			(new File(file)).delete();
		}
		(new File(directory)).delete();
	}
	
	public static void cleanTempPath() {
		String tempPath=System.getProperty("java.io.tmpdir");
		FiltroGenerico fg=new FiltroGenerico();
		Vector<String> directorios=fg.loadFiles(tempPath, ".counter");
		for (String directorio : directorios) {
			Vector<String> files = fg.loadFiles(directorio, null);
			for (String file : files) {
				(new File(file)).delete();
			}
			(new File(directorio)).delete();
		}
	}

	public static void saveResult(String resultsPath, String aspectFamilyName, String aspectClassFile, String catchedMethodName, String testCaseName, int callNumber, String result) throws IOException {
		aspectClassFile=aspectClassFile.replace('/', '.');
		String fileName=resultsPath + aspectClassFile + ".txt";
		FileWriter fos=new FileWriter(fileName, true);
		PrintWriter pos=new PrintWriter(fos);
		String linea=aspectFamilyName + "\t" + catchedMethodName + "\t" + testCaseName + "\t" + callNumber + "\t" + result;
		pos.println(linea);
		fos.close();
	}
}
